home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / sox / wav.c < prev   
C/C++ Source or Header  |  1994-08-01  |  5KB  |  214 lines

  1. /*
  2.  * April 15, 1992
  3.  * Copyright 1992 Rick Richardson
  4.  * Copyright 1991 Lance Norskog And Sundry Contributors
  5.  * This source code is freely redistributable and may be used for
  6.  * any purpose.  This copyright notice must be maintained. 
  7.  * Lance Norskog And Sundry Contributors are not responsible for 
  8.  * the consequences of using this software.
  9.  */
  10.  
  11. /*
  12.  * Windows 3.0 .wav format driver
  13.  */
  14.  
  15. /*
  16.  * Fixed by various contributors:
  17.  * 1) Little-endian handling
  18.  * 2) Skip other kinds of file data
  19.  * 3) Handle 16-bit formats correctly
  20.  * 4) Not go into infinite loop
  21.  */
  22.  
  23. #include "st.h"
  24.  
  25. /* Private data for .wav file */
  26. typedef struct wavstuff {
  27.     long    samples;
  28. } *wav_t;
  29.  
  30. IMPORT float volume, amplitude;
  31. IMPORT long summary, verbose;
  32.  
  33. /*
  34.  * Do anything required before you start reading samples.
  35.  * Read file header. 
  36.  *    Find out sampling rate, 
  37.  *    size and style of samples, 
  38.  *    mono/stereo/quad.
  39.  */
  40. wavstartread(ft) 
  41. ft_t ft;
  42. {
  43.     wav_t    wav = (wav_t) ft->priv;
  44.     char    magic[4];
  45.     long    len;
  46.     int    littlendian = 1;
  47.     char    *endptr;
  48.     char    c;
  49.  
  50.     endptr = (char *) &littlendian;
  51.     if (!*endptr) ft->swap = 1;
  52.  
  53.     /* If you need to seek around the input file. */
  54.     if (0 && ! ft->seekable)
  55.         fail(".wav input file must be a file, not a pipe");
  56.  
  57.     fread(magic, 4, 1, ft->fp);
  58.     if (strncmp("RIFF", magic, 4))
  59.         fail("Not a RIFF file");
  60.  
  61.     len = rllong(ft);
  62.  
  63.     fread(magic, 4, 1, ft->fp);
  64.     if (strncmp("WAVE", magic, 4))
  65.         fail("Not a WAVE file");
  66.  
  67.     fread(magic, 4, 1, ft->fp);
  68.     if (strncmp("fmt ", magic, 4))
  69.         if (strncmp("LIST", magic, 4))
  70.             fail("Missing fmt spec");
  71.         else {
  72.             for (len = rllong(ft);len--;len>0)
  73.                 fread(&c,1,1,ft->fp);
  74.             fread(magic, 4, 1, ft->fp);
  75.             if (strncmp("fmt ", magic, 4))
  76.                 fail("Missing fmt spec");
  77.               }
  78.  
  79.  
  80.     len = rllong(ft);
  81.     switch (rlshort(ft))
  82.     {
  83.     case 1:        break;
  84.     default:    fail("Don't understand format");
  85.     }
  86.     ft->info.channels = rlshort(ft);
  87.     ft->info.rate = rllong(ft);
  88.     rllong(ft);    /* Average bytes/second */
  89.     rlshort(ft);    /* Block align */
  90.     switch (rlshort(ft))
  91.     {
  92.     case 8:        ft->info.size = BYTE; ft->info.style = UNSIGNED; break;
  93.     case 16:    ft->info.size = WORD; ft->info.style = SIGN2; break;
  94.     case 32:    ft->info.size = LONG; ft->info.style = SIGN2; break;
  95.     default:    fail("Don't understand size");
  96.     }
  97.     len -= 16;
  98.     while (--len >= 0) getc(ft->fp);
  99.  
  100.     fread(magic, 4, 1, ft->fp);
  101.     if (strncmp("data", magic, 4))
  102.         fail("Missing data portion");
  103.  
  104.     wav->samples = rllong(ft);
  105. }
  106.  
  107. /*
  108.  * Read up to len samples from file.
  109.  * Convert to signed longs.
  110.  * Place in buf[].
  111.  * Return number of samples read.
  112.  */
  113.  
  114. wavread(ft, buf, len) 
  115. ft_t ft;
  116. long *buf, len;
  117. {
  118.     wav_t    wav = (wav_t) ft->priv;
  119.     int    done;
  120.  
  121.     if (len > wav->samples) len = wav->samples;
  122.     if (len == 0) return 0;
  123.     done = rawread(ft, buf, len);
  124.     wav->samples -= len;
  125.     return done;
  126. }
  127.  
  128. /*
  129.  * Do anything required when you stop reading samples.  
  130.  * Don't close input file! 
  131.  */
  132. wavstopread(ft) 
  133. ft_t ft;
  134. {
  135. }
  136.  
  137. wavstartwrite(ft) 
  138. ft_t ft;
  139. {
  140.     wav_t    wav = (wav_t) ft->priv;
  141.     int    littlendian = 1;
  142.     char    *endptr;
  143.  
  144.     if (! ft->seekable)
  145.         fail("Output .wav file must be a file, not a pipe");
  146.  
  147.     endptr = (char *) &littlendian;
  148.     if (!*endptr) ft->swap = 1;
  149.  
  150.     wav->samples = 0;
  151.     wavwritehdr(ft);
  152. }
  153.  
  154. wavwritehdr(ft) 
  155. ft_t ft;
  156. {
  157.     wav_t    wav = (wav_t) ft->priv;
  158.     int    samsize;
  159.     long    datasize;
  160.  
  161.     switch (ft->info.size)
  162.     {
  163.     case BYTE:    samsize = 8; ft->info.style = UNSIGNED; break;
  164.     case WORD:    samsize = 16; ft->info.style = SIGN2; break;
  165.     default:
  166.     case LONG:    ft->info.size = LONG; ft->info.style = SIGN2; 
  167.             samsize = 32; break;
  168.     }
  169.     
  170.  
  171.     datasize = samsize/8 * ft->info.channels * wav->samples;
  172.  
  173.     fputs("RIFF", ft->fp);
  174.     wllong(ft, datasize + 8+16+12);    /* Waveform chunk size: FIXUP(4) */
  175.     fputs("WAVE", ft->fp);
  176.     fputs("fmt ", ft->fp);
  177.     wllong(ft, (long)16);        /* fmt chunk size */
  178.     wlshort(ft, 1);            /* FormatTag: WAVE_FORMAT_PCM */
  179.     wlshort(ft, ft->info.channels);
  180.     wllong(ft, (long)ft->info.rate);    /* SamplesPerSec */
  181.                     /* Average Bytes/sec */
  182.     wllong(ft, ((long)ft->info.rate * ft->info.channels * samsize + 7) / 8);
  183.                     /* nBlockAlign */
  184.     wlshort(ft, (ft->info.channels * samsize + 7) / 8);
  185.     wlshort(ft, samsize);        /* BitsPerSample */
  186.     
  187.     fputs("data", ft->fp);
  188.     wllong(ft, datasize);        /* data chunk size: FIXUP(40) */
  189. }
  190.  
  191. wavwrite(ft, buf, len) 
  192. ft_t ft;
  193. long *buf, len;
  194. {
  195.     wav_t    wav = (wav_t) ft->priv;
  196.  
  197.     wav->samples += len * ft->info.size;
  198.     rawwrite(ft, buf, len);
  199. }
  200.  
  201. void
  202. wavstopwrite(ft) 
  203. ft_t ft;
  204. {
  205.     /* All samples are already written out. */
  206.     /* If file header needs fixing up, for example it needs the */
  207.      /* the number of samples in a field, seek back and write them here. */
  208.     if (!ft->seekable)
  209.         return;
  210.     if (fseek(ft->fp, 0L, 0) != 0)
  211.         fail("Can't rewind output file to rewrite .wav header.");
  212.     wavwritehdr(ft);
  213. }
  214.